
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.CodeDom;
using System.Reflection;
using System.Reflection.Emit;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Globalization;

namespace ConsoleApplication5
{
    /// <summary>
    /// Emit 和 CodeDom 都是用来动态创建类型，并利用反射执行的东东~~~~ 
    /// </summary>
    class Program
    {
        static void Main1(string[] args)
        {
            /*
            //一，Emit 则直接使用 IL
            //1. 定义动态程序集
            AssemblyName assemblyName = new AssemblyName("Nettip.Assembly");
            AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);

            //2. 定义动态模块
            ModuleBuilder module = assembly.DefineDynamicModule("Nettip.QueryOrderConditon.Module");

            //3. 定义类型
            TypeBuilder type = module.DefineType("QueryOrderCondition", TypeAttributes.Class, typeof(object));

            //4. 定义方法
            MethodBuilder method = type.DefineMethod("Test", MethodAttributes.Public, CallingConventions.HasThis, null, null);

            //5. 方法代码
            ILGenerator il = method.GetILGenerator();
            il.Emit(OpCodes.Nop);
            il.Emit(OpCodes.Ldstr, "Hello, World!");
            il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
            il.Emit(OpCodes.Nop);
            il.Emit(OpCodes.Ret);

            //6. 执行
            Type class1 = type.CreateType();
            object o = Activator.CreateInstance(class1);
            o.GetType().GetMethod("Test").Invoke(o, null);
            */
            //二，CodeDom 利用 C#/VB.NET 等编译引擎进行动态编译

            #region
            // 1. 使用CodeDom创建源码
            //CodeCompileUnit cu = new CodeCompileUnit();
            //CodeNamespace Samples = new CodeNamespace("Samples");
            //cu.Namespaces.Add(Samples); 
            //Samples.Imports.Add(new CodeNamespaceImport("System"));             
            //CodeTypeDeclaration Class1 = new CodeTypeDeclaration("Class1"); 
            //Samples.Types.Add(Class1); 
            //CodeEntryPointMethod Start = new CodeEntryPointMethod(); 
            //CodeMethodInvokeExpression cs1 = new CodeMethodInvokeExpression(  
            //    new CodeTypeReferenceExpression("System.Console"), "WriteLine", 
            //    new CodePrimitiveExpression("Hello World!") );
            //Start.Statements.Add(new CodeExpressionStatement(cs1));
            //Class1.Members.Add(Start); 

            string code = @"
                using System;
                namespace Nettip
                {
                    public class QueryOrderCondition
                    
                        private string name;

                        public QueryOrderCondition(string name)
                        {
                            this.name = name;
                        }

                        public void Test()
                        {
                            Console.WriteLine(""{0} - {1}"", name, DateTime.Now);
                        }
                    }
                }
            ";

            #endregion
            //1. 创建编译器对象
            CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");

            //2. 设置编译参数
            CompilerParameters cp = new CompilerParameters();
            cp.ReferencedAssemblies.Add("System.dll");
            cp.GenerateInMemory = false;
            cp.OutputAssembly = "Nettip.QueryOrderCondition.dll";

            //3. 开始编译
            CompilerResults results = provider.CompileAssemblyFromSource(cp, code);
            //3.1 显示编译信息
            if (results.Errors.Count == 0)
                Console.WriteLine("\"{0}\" compiled ok!", results.CompiledAssembly.Location);
            else
            {
                Console.WriteLine("Complie Error:");
                foreach (CompilerError error in results.Errors)
                    Console.WriteLine("  {0}", error);
            }

            //4.执行
            Type t = results.CompiledAssembly.GetType("Nettip.QueryOrderCondition");
            object o = results.CompiledAssembly.CreateInstance("Nettip.QueryOrderCondition", false, BindingFlags.Default,
                null, new object[] { "Tom" }, CultureInfo.CurrentCulture, null);
            t.InvokeMember("Test", BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod,
                null, o, null);
        }
    }
}